import type { BorrowerRecord } from "./borrower-record";
import client from "./client";
import type { LibrarianRecord } from "./librarian-record";
import type { Resp } from "./resp";
import type { BookRecord } from "./book-record";
import type { TransactionRecord, BorrowTransactionStatus } from "./transaction-record";

export type UserInfo = {
    email: string;
    password: string;
};

function getBasicAuthHeader(userInfo: UserInfo) {
    return 'Basic ' + btoa(`${userInfo.email}:${userInfo.password}`);
}

// auth-service
export function registerLibrarian(librarianRecord: LibrarianRecord) {
    return client.post<Resp<boolean>>('/auth-service/register/librarian', librarianRecord);
}

export function registerBorrower(borrowerRecord: BorrowerRecord) {
    return client.post<Resp<boolean>>('/auth-service/register/borrower', borrowerRecord);
}

// auth-service
export function authenticateBorrower(borrowerRecord: BorrowerRecord, userInfo: UserInfo) {
    return client.post<Resp<boolean>>('/auth-service/borrower', borrowerRecord, {
        headers: {
            'Authorization': getBasicAuthHeader(userInfo)
        }
    });
}

export function authenticateLibrarian(librarianRecord: LibrarianRecord, userInfo: UserInfo) {
    return client.post<Resp<boolean>>('/auth-service/librarian', librarianRecord, {
        headers: {
            'Authorization': getBasicAuthHeader(userInfo)
        }
    });
}

// @RestController
// @RequestMapping("/auth")
// @RequiredArgsConstructor
// @RateLimiter(name = "default-ratelimiter")
// @Bulkhead(name = "default-bulkhead")
// @CircuitBreaker(name = "default-circuitbreaker")
// public class AuthController implements AuthApi {
//     private final AuthService authService;

//     @PostMapping("/borrower")
//     public Resp<Boolean> authenticateBorrower(@RequestBody BorrowerRecord borrowerRecord) {
//         return Resp.success(authService.authenticateBorrower(borrowerRecord));
//     }

//     @PostMapping("/librarian")
//     public Resp<Boolean> authenticateLibrarian(@RequestBody LibrarianRecord librarianRecord) {
//         System.out.println("========================\nauthenticate librarian");
//         return Resp.success(authService.authenticateLibrarian(librarianRecord));
//     }
// }

// book-service
export function searchBooks(title?: string, author?: string, isbn?: string, available?: boolean, page: number = 0, size: number = 10, sort: string = 'id', direction: 'asc' | 'desc' = 'desc', userInfo?: UserInfo) {
    return client.get<Resp<{
        content: BookRecord[],
    }>>(`/book-service/book/search`, {
        params: {
            title,
            author,
            isbn,
            available,
            page,
            size,
            sort,
            direction: direction.toUpperCase()
        },
        headers: userInfo ? {
            'Authorization': getBasicAuthHeader(userInfo)
        } : {}
    });
}

export function createBook(bookRecord: BookRecord, userInfo: UserInfo) {
    return client.post<Resp<BookRecord>>(`/book-service/book`, bookRecord, {
        headers: {
            'Authorization': getBasicAuthHeader(userInfo)
        }
    });
}

export function removeBook(id: number, userInfo: UserInfo) {
    return client.delete<Resp<boolean>>(`/book-service/book/${id}`, {
        headers: {
            'Authorization': getBasicAuthHeader(userInfo)
        }
    });
}

export function addCopies(command: { bookId: number, copies: number }, userInfo: UserInfo) {
    return client.put<Resp<boolean>>(`/book-service/book/${command.bookId}/addCopies`, {}, {
        params: {
            copies: command.copies
        },
        headers: {
            'Authorization': getBasicAuthHeader(userInfo)
        }
    });
}

export function removeCopies(command: { bookId: number, copies: number }, userInfo: UserInfo) {
    return client.put<Resp<boolean>>(`/book-service/book/${command.bookId}/removeCopies`, {}, {
        params: {
            copies: command.copies
        },
        headers: {
            'Authorization': getBasicAuthHeader(userInfo)
        }
    });
}

// baseurl /book-service/book
// @PostMapping("")
// public Resp<BookRecord> createBook(@RequestBody BookRecord bookRecord) {
//     bookService.createBook(bookRecord.toEntity());
//     return Resp.success(bookRecord);
// }

// @DeleteMapping("/{id}")
// public Resp<Boolean> removeBook(@PathVariable Long id) {
//     bookService.removeBook(id.intValue());
//     return Resp.success(true);
// }

// @RestController
// @RequestMapping("/book")
// @RequiredArgsConstructor
// @RateLimiter(name = "default-ratelimiter")
// @Bulkhead(name = "default-bulkhead")
// @CircuitBreaker(name = "default-circuitbreaker")
// public class BookController {
//     private final BookService bookService;

//     @GetMapping("/search")
//     public Resp<Page<BookRecord>> searchBooks(
//             @RequestParam(required = false) String title,
//             @RequestParam(required = false) String author,
//             @RequestParam(required = false) String isbn,
//             @RequestParam(required = false) Boolean available,
//             @PageableDefault(size = 10, sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {
//         return Resp.success(bookService.searchBooks(title, author, isbn, available, pageable));
//     }

//     @PostMapping("/add")
//     public Resp<Boolean> addCopies(@RequestBody AddBookCopiesCommand command) {
//         return Resp.success(bookService.addCopies(command));
//     }

//     @PostMapping("/remove")
//     public Resp<Boolean> removeCopies(@RequestBody RemoveBookCopiesCommand command) {
//         return Resp.success(bookService.removeCopies(command));
//     }
// }

// borrow-service
export function searchTransactions(borrowerId?: number, bookId?: number, beginTime?: string, endTime?: string, returned?: boolean, page: number = 0, size: number = 10, sort: string = 'borrowDate', direction: 'asc' | 'desc' = 'desc', userInfo?: UserInfo) {
    return client.get<Resp<{
        content: TransactionRecord[];
    }>>('/borrow-service/transaction/search', {
        params: {
            borrowerId,
            bookId,
            beginTime,
            endTime,
            returned,
            page,
            size,
            sort,
            direction
        },
        headers: userInfo ? {
            'Authorization': getBasicAuthHeader(userInfo)
        } : {}
    });
}

export function createTransaction(command: { bookId: number, borrowerId: number }, userInfo: UserInfo) {
    return client.post<Resp<boolean>>('/borrow-service/transaction', command, {
        headers: {
            'Authorization': getBasicAuthHeader(userInfo)
        }
    });
}

export function returnTransaction(id: number, userInfo: UserInfo) {
    return client.post<Resp<boolean>>(`/borrow-service/transaction/${id}/return`, {}, {
        headers: {
            'Authorization': getBasicAuthHeader(userInfo)
        }
    });
}
// @RestController
// @RequestMapping("/transaction")
// @RequiredArgsConstructor
// @RateLimiter(name = "default-ratelimiter")
// @Bulkhead(name = "default-bulkhead")
// @CircuitBreaker(name = "default-circuitbreaker")
// public class TransactionController {
//     private final TransactionService transactionService;

//     @GetMapping("/search")
//     public Resp<Page<TransactionRecord>> search(
//             @RequestParam(required = false) Long borrowerId,
//             @RequestParam(required = false) Long bookId,
//             @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime beginTime,
//             @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime,
//             @RequestParam(required = false, defaultValue = "false") Boolean returned,
//             @PageableDefault(size = 10, sort = "borrowDate", direction = Sort.Direction.DESC) Pageable pageable) {
//         return Resp.success(transactionService.search(borrowerId, bookId, beginTime, endTime, returned, pageable));
//     }

//     @PostMapping("/create")
//     public Resp<Boolean> create(@RequestBody CreateTransactionCommand command) {
//         return Resp.success(transactionService.create(command));
//     }

//     @PostMapping("/{id}/return")
//     public Resp<Boolean> close(@PathVariable Long id) {
//         return Resp.success(transactionService.close(id));
//     }
// }

// common-service
export function ping(userInfo?: UserInfo) {
    return client.get<Resp<string>>('/common-service/ping', {
        headers: userInfo ? {
            'Authorization': getBasicAuthHeader(userInfo)
        } : {}
    });
}

// @RestController
// public class PingController {
//     @GetMapping("/ping")
//     public Resp<String> ping() {
//         return Resp.success("pong");
//     }
// }

// export {
//   BorrowTransactionStatus
// } from "./transaction-record";
